﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Mvc;
using Autofac;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Vowei.Core.Models;
using Vowei.Data;
using Vowei.Data.Helpers;
using Vowei.Core;
using System.Globalization;

namespace Vowei.Web.Helpers
{
    public static class ViewHelpers
    {
        public const string JsonObjectKey = "JsonObject";
        public const string JsonObjectName = "server_json_object";
        
        public static string GetLogonUserName()
        {
            return MvcApplication.ContainerProviderStatic.ApplicationContainer.Resolve<IUser>().UserName;
        }

        public static void WriteClientTemplate(this WebViewPage page, string type, string action)
        {
            var templateText = File.ReadAllText(
                page.Server.MapPath(string.Format("~/Content/tmpl/{0}{1}.html", type, action)));
            var text = new HtmlString(string.Format("<script type=\"text/x-jquery-tmpl\" id=\"item_template\">{0}</script>",
                templateText));
            page.Write(text);
        }

        public static void WriteClientTemplateScript(this WebViewPage page)
        {
            var text = new HtmlString(string.Format("<script language=\"javascript\" type=\"text/javascript\">\n" +
                                                    "applyServerTemplate({0});\n" +
                                                    "</script>",
                                                    page.ViewData[JsonObjectKey]));
            page.Write(text);
        }

        public static T AddJsonSupport<T>(this T view)
            where T : ViewResult
        {
            var model = view.ViewData.Model;

            // 强制执行查询
            if (model is IQueryable)
            {
                throw new InvalidOperationException("视图的数据是一个IQueryable实例，请先将IQueryable保存的查询显式执行完再调用该函数！");
            }

            view.ViewData[JsonObjectKey] = ViewHelpers.SerializeToJson(model);
            return view;
        }

        public static string ToJson(this object item)
        {
            return SerializeToJson(item, null);
        }  

        private static List<JsonConverter> _converters;
        private static EntityProxyContractResolver _proxyResolver = new EntityProxyContractResolver();
        public static string SerializeToJson(object item)
        {
            return SerializeToJson(item, null);
        }

        public static string SerializeToJson(object item, List<JsonConverter> converters)
        {
            if (converters == null)
            {
                if (_converters == null)
                {
                    _converters = new List<JsonConverter>();
                    _converters.Add(new JavaScriptDateTimeConverter());
                }

                converters = _converters;
            }

            var settings = new JsonSerializerSettings()
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
                Converters = converters,
                ContractResolver = _proxyResolver
            };

            return JsonConvert.SerializeObject(item, Formatting.None, settings);
        }

        public static string GetControllerNameFor(Type type)
        {
            return EntityHelpers.GetEntityTypeName(type);
        }
    }

    internal class EntityProxyContractResolver : DefaultContractResolver
    {
        protected override List<MemberInfo> GetSerializableMembers(Type objectType)
        {
            if (EntityHelpers.IsEntityProxyType(objectType))
                return base.GetSerializableMembers(objectType.BaseType);
            else
                return base.GetSerializableMembers(objectType);
        }
    }
}